
#include "StdAfx.h"
#include "SELECT_IOListener.h"
#include "SessionSync.h"
#include <algorithm>
#include "NetService.h"

SELECT_IOListener::SELECT_IOListener(){	
	FD_ZERO( &listen_fd_ );
}

SELECT_IOListener::~SELECT_IOListener(){
	stop();
	FD_ZERO( &listen_fd_ );
}

bool SELECT_IOListener::initialize( unsigned int event_size, int port, int back_log){
	if( port ){
		if(! listen_.listen( port, back_log ) ){
			LOG_ERR( LOG_SERVICE( "instance" )->Log("%s - %u", __FUNCTION__, __LINE__) );
			return false;
		}
		
		FD_SET( listen_.getPeer(), &listen_fd_ );
	}
	
	CThread::start(0, this);
	return true;
}

bool SELECT_IOListener::registerSession( NetworkSession* session ){	
	event_descripters_.push_back( session );
	return true;
}

bool SELECT_IOListener::unregisterSession( NetworkSession* session ){	
	return true;
}

int SELECT_IOListener::acceptSession(){
	timeval wait_time;
	wait_time.tv_sec = 0;
	wait_time.tv_usec = DEF_WAIT_LISTEN_TIME;

	FD_ZERO( &listen_fd_ );
	FD_SET( listen_.getPeer(), &listen_fd_ );

	int total_event_count = select( (listen_.getPeer() + 1), &listen_fd_, 0, 0, &wait_time);
	
	if( total_event_count <= 0 )
		return total_event_count;	

	char ip[ DEF_IP_LEN ];
	memset( ip, 0, DEF_IP_LEN );
	SOCKET sock = listen_.accept_socket( ip );

	if( sock == INVALID_SOCKET ){		
		LOG_ERR( LOG_SERVICE( "instance" )->Log("%s - %u - sock = %i ", __FUNCTION__, __LINE__, \
			sock) );

		return total_event_count;
	}
	
	Socket socket;
	socket.setPeer( sock, ip );
	if(! NetService::Instance()->registerSession( socket ) ){		
		LOG_ERR( LOG_SERVICE( "instance" )->Log("%s - %u - sock = %i", __FUNCTION__, __LINE__, \
			sock) );

		socket.close_socket();
	}	

	return total_event_count;
}

int SELECT_IOListener::ioListener_process(){
	int total_event_count = 0;
	NetworkSession* session = 0;
	EventDescripters::iterator itr;	

	timeval wait_time;
	wait_time.tv_sec = 0;
	wait_time.tv_usec = DEF_WAIT_EVENT_TIME;	
	fd_set read_fds;

	if( listen_.getPeer() != INVALID_SOCKET )
		acceptSession();

	if(! event_descripters_.size() )
		return 0;
		
	for( itr = event_descripters_.begin() ; itr != event_descripters_.end() ; ){
		session = *itr;

		if( session->getPeer() == INVALID_SOCKET ){
			event_descripters_.erase( itr++ );
			session->close_handler( 0, "SELECT_IOListener" );
			continue;
		}

		FD_ZERO( &read_fds );
		FD_SET( session->getPeer(), &read_fds );
		total_event_count = select( ( session->getPeer() + 1 ), &read_fds, 0, 0, &wait_time );
			
		/*
		if(! FD_ISSET( session->getPeer(), &read_fds ) ){
			itr++;
			continue;
		}
		*/
			
		if(! total_event_count ){
			itr++;
			continue;
		}

		if( total_event_count < 0 ){				
			event_descripters_.erase( itr++ );
			session->close_handler( 0, "SELECT_IOListener" );
			continue;
		}

		if( session->read_handler() < 0 ){
			event_descripters_.erase( itr++ );	
			session->close_handler( 0, "SELECT_IOListener" );	
			continue;
		}

		itr++;
	}	
	
	return 0;
}

DEF_THREAD_RETURN SELECT_IOListener::run(){	
	LOG_INSTANCE( LOG_SERVICE( "instance" )->Log("select thread start %s = %u" \
			, __FILE__, getThreadID()) );

	while( isActive() )
		SLEEP( DEF_WAIT_BUSY );		

	LOG_INSTANCE( LOG_SERVICE( "instance" )->Log("thread end %s = %u" \
			, __FILE__, getThreadID()) );	
}
